﻿using Brc_PaaS.Bll.System;
using Brc_PaaS.Common.Entity;
using Brc_PaaS.Common.Model.Apollo;
using Brc_PaaS.Common.Model.Basic;
using Brc_PaaS.Core.Apollo.Service;
using Brc_PaaS.Dal;
using Exceptionless;
using Exceptionless.Logging;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Brc_PaaS.Bll.Apollo
{
    public class Apollo : IApollo
    {
        private readonly IRepository<Ass_Apollo> apolloRepository;
        private readonly IApolloNamespaceService apolloNamespaceService;
        private readonly ISystem systemService;
        private readonly IApolloConfigService apolloConfigService;
        private readonly IConfiguration configuration;

        string env = string.Empty;//apollo的环境  ENV支持以下几个值： DEV、FAT、UAT、Pro
        string saveUserId = "";//添加修改的用户
        string portAdderess = string.Empty;
        string releaseUserId = "";//发布的用户

        public Apollo(IRepository<Ass_Apollo> apolloRepository,
            IApolloNamespaceService apolloNamespaceService,
            IApolloConfigService apolloConfigService,
            ISystem system,
            IConfiguration configuration)
        {
            this.apolloRepository = apolloRepository;
            this.apolloNamespaceService = apolloNamespaceService;
            this.apolloConfigService = apolloConfigService;
            this.systemService = system;
            this.configuration = configuration;
            InitCofig();
        }

        public void InitCofig()
        {
            env = configuration.GetValue<string>("Apollo:Environment");
            saveUserId = configuration.GetValue<string>("Apollo:SaveUser");
            releaseUserId = configuration.GetValue<string>("Apollo:ReleaseUser");
            portAdderess = configuration.GetValue<string>("Apollo:PortalAddress");
        }

        /// <summary>
        /// 创建匿名空间
        /// </summary>
        /// <param name="createNamespaceViewDto"></param>
        /// <returns></returns>
        public ResponseModel<string> CreateNamespace(CreateNamespaceViewDto createNamespaceViewDto)
        {
            var result = new ResponseModel<string> { IsSuccess = false };

            if (createNamespaceViewDto == null)
            {
                result.Msg = "创建匿名空间信息对象为空";
                return result;
            }

            // 检查该系统是否已经存在匿名空间,一个系统只能有一个匿名空间
            var namespaceInfoDto = GetNamespaceBySystemId(createNamespaceViewDto.SystemId);
            if (namespaceInfoDto != null && namespaceInfoDto.IsSuccess && namespaceInfoDto.Data != null)
            {
                result.Msg = "该系统已经存在匿名空间";
                return result;
            }

            // 检查匿名空间，是否已存在数据库中
            namespaceInfoDto = GetNamespaceByNamespaceName(createNamespaceViewDto.Name);
            if (namespaceInfoDto != null && namespaceInfoDto.IsSuccess && namespaceInfoDto.Data != null)
            {
                result.Msg = "匿名空间已存在，请换一个匿名空间";
                return result;
            }

            var system = systemService.GetSystem(createNamespaceViewDto.SystemId);
            if (system == null || system.IsSuccess == false || system.Data == null)
            {
                result.Msg = "未找到系统信息";
                return result;
            }

            var registerApolloResult = apolloNamespaceService.CreateNamespaceInfo(new CreateNamespaceDto()
            {
                AppId = createNamespaceViewDto.AppId,
                Token = createNamespaceViewDto.Token,
                Format = "properties",
                IsPublic = false,
                Name = createNamespaceViewDto.Name,
                Portal_address = portAdderess,
                Comment = "",
                dataChangeCreatedBy = saveUserId
            });
            if (registerApolloResult == null || registerApolloResult.IsSuccess == false || registerApolloResult.Data == null || string.IsNullOrWhiteSpace(registerApolloResult.Data.Name))
            {
                WriteLog("CreateNamespace", system.Data.Name, system.Data.Id, "修改配置", registerApolloResult.Msg);
                result.Msg = "创建匿名空间出错，请联系管理员";

                return result;
            }

            var accountInfo = new Ass_Apollo()
            {
                CreateTime = DateTime.Now,
                Id = Guid.NewGuid().ToString("N"),
                Status = 1,
                CreateUserId = createNamespaceViewDto.CreateUserId,
                Namespace = createNamespaceViewDto.Name,
                SystemId = createNamespaceViewDto.SystemId,
                Token = createNamespaceViewDto.Token,
                AppId=createNamespaceViewDto.AppId
            };

            var affectNumber = apolloRepository.AddItem(accountInfo);

            if (affectNumber <= 0)
            {
             
                WriteLog("CreateNamespace", system.Data.Name, system.Data.Id, "创建匿名空间", "添加到数据库失败",JsonConvert.SerializeObject(accountInfo));
                result.Msg = "添加到数据库失败";
                return result;
            }

            result = new ResponseModel<string>()
            {
                IsSuccess = true,
                Data = accountInfo.Id
            };
            return result;
        }


        /// <summary>
        /// 保存配置信息
        /// </summary>
        /// <param name="createConfigViewDto"></param>
        /// <returns></returns>
        public BaseResponseModel SaveConfig(CreateConfigViewDto createConfigViewDto)
        {
            var result = new BaseResponseModel { IsSuccess = false };

            if (createConfigViewDto == null)
            {
                result.Msg = "保存配置对象为空";
                return result;
            }

            var systemInfo = systemService.GetSystem(createConfigViewDto.SystemId);
            if (systemInfo == null || !systemInfo.IsSuccess || systemInfo.Data == null)
            {
                result.Msg = "未找到系统信息";
                return result;
            }

            var namespaceInfo = GetNamespaceBySystemId(createConfigViewDto.SystemId);
            if (namespaceInfo == null || !namespaceInfo.IsSuccess || namespaceInfo.Data == null)
            {
                result.Msg = "未找到匿名空间信息";
                return result;
            }

            var releaseConfigDto = GetEffectiveConfigInfo(systemInfo.Data, namespaceInfo.Data);
            if (releaseConfigDto == null || !releaseConfigDto.IsSuccess)
            {
                result.Msg = "获取配置失败，请联系管理员";
                return result;
            }

            var configList = releaseConfigDto.Data?.Configurations;
            var createOrUpdateConfigInfoDto = new CreateOrUpdateConfigInfoDto()
            {
                AppId = namespaceInfo.Data.AppId,
                ClusterName = "default",
                Key = createConfigViewDto.Key,
                Comment = createConfigViewDto.Comment,
                Env = env,//apollo的环境  ENV支持以下几个值： DEV、FAT、UAT、Pro,
                NamespaceName = namespaceInfo.Data.Namespace,
                Token = namespaceInfo.Data.Token,
                Value = createConfigViewDto.Value,
                DataChangeCreatedBy = saveUserId,
                Portal_address = portAdderess,
                DataChangeLastModifiedBy= saveUserId
            };
            if (configList != null && configList.ContainsKey(createConfigViewDto.Key))
            {

                var responseModel = apolloConfigService.UpdateConfig(createOrUpdateConfigInfoDto);
                if (responseModel == null || !responseModel.IsSuccess)
                {
                    WriteLog("SaveConfig", systemInfo.Data.Name, systemInfo.Data.Id, "修改配置", responseModel.Msg);
                    result.Msg = "修改配置信息失败，请联系管理员" ;
                    return result;
                }
            }
            else
            {
                var responseModel = apolloConfigService.AddConfig(createOrUpdateConfigInfoDto);
                if (responseModel == null || !responseModel.IsSuccess)
                {
                    WriteLog("SaveConfig", systemInfo.Data.Name, systemInfo.Data.Id, "添加配置", responseModel.Msg);

                    result.Msg = "添加配置失败，请联系管理员";
                    return result;
                }
            }
           return ReleaseConfig(systemInfo, namespaceInfo, createConfigViewDto.Key);

        }

        /// <summary>
        /// 删除配置
        /// </summary>
        /// <param name="deleteConfigViewDto"></param>
        /// <returns></returns>
        public BaseResponseModel DeleteConfig(DeleteConfigViewDto deleteConfigViewDto)
        {
            var result = new BaseResponseModel { IsSuccess = false };
            var systemInfo = systemService.GetSystem(deleteConfigViewDto.SystemId);
            if (systemInfo == null || !systemInfo.IsSuccess || systemInfo.Data == null)
            {
                result.Msg = "未找到系统信息";
                return result;
            }

            var namespaceInfo = GetNamespaceBySystemId(deleteConfigViewDto.SystemId);
            if (namespaceInfo == null || !namespaceInfo.IsSuccess || namespaceInfo.Data == null)
            {
                result.Msg = "未找到匿名空间信息";
                return result;
            }

            var deleteConfigResult = apolloConfigService.DeleteConfig(new DeleteConfigDto()
            {
                AppId = namespaceInfo.Data.AppId,
                ClusterName = "default",
                Env = env,
                Token = namespaceInfo.Data.Token,
                NamespaceName = namespaceInfo.Data.Namespace,
                Key = deleteConfigViewDto.Key,
                Operator = saveUserId,
                Portal_address = portAdderess
            });

            if (deleteConfigResult == null || !deleteConfigResult.IsSuccess)
            {
                WriteLog("DeleteConfig", systemInfo.Data.Name, systemInfo.Data.Id, "删除配置", deleteConfigResult.Msg);
                result.Msg = "删除配置失败,请联系管理员";
                return result;
            }

            return ReleaseConfig(systemInfo, namespaceInfo, deleteConfigViewDto.Key);
        }

        /// <summary>
        /// 获取配置
        /// </summary>
        /// <param name="key"></param>
        /// <param name="systemId"></param>
        /// <returns></returns>
        public ResponseModel<string> GetConfig(string key, Bas_System systemInfo, Ass_Apollo apollo)
        {
            var result = new ResponseModel<string> { IsSuccess = false };

            var configList = GetConfigs(systemInfo, apollo);
            if (configList == null || !configList.IsSuccess || configList.Data == null)
            {
                return result;
            }
            if(configList.Data!=null && configList.Data.ContainsKey(key))
            {
                result.Data = configList.Data[key];
            }
            result.IsSuccess = true;
            return result;
        }

        private ResponseModel<Dictionary<string, string>> GetConfigs(Bas_System systemInfo, Ass_Apollo apollo)
        {
            var result = new ResponseModel<Dictionary<string, string>> { IsSuccess = false };


            var releaseConfigDto = GetEffectiveConfigInfo(systemInfo, apollo);
            if (releaseConfigDto == null || !releaseConfigDto.IsSuccess)
            {
               
                result.Msg = "获取配置失败，请联系管理员";
                return result;
            }
            result.Data = releaseConfigDto.Data?.Configurations;
            result.IsSuccess = true;
            return result;
        }

        public ResponseModel<Ass_Apollo> GetNamespaceBySystemId(string systemId)
        {
            ResponseModel<Ass_Apollo> result = new ResponseModel<Ass_Apollo>() { IsSuccess = false };
            if (string.IsNullOrWhiteSpace(systemId))
            {
                result.Msg = "systemId不能为空";
                return result;
            }
            result.Data = apolloRepository.Get(i => i.SystemId == systemId);
            result.IsSuccess = true;
            return result;
        }

        private ResponseModel<Ass_Apollo> GetNamespaceByNamespaceName(string namespaceName)
        {
            ResponseModel<Ass_Apollo> result = new ResponseModel<Ass_Apollo>() { IsSuccess = false };
            if (string.IsNullOrWhiteSpace(namespaceName))
            {
                result.Msg = "namespaceName不能为空";


                return result;
            }
            result.Data = apolloRepository.Get(i => i.Namespace == namespaceName);
            result.IsSuccess = true;
            return result;
        }



        private BaseResponseModel ReleaseConfig(ResponseModel<Bas_System> systemInfo, ResponseModel<Ass_Apollo> namespaceInfo, string key)
        {
            var result = new BaseResponseModel() { IsSuccess = false };
            var releaseConfigResult = apolloConfigService.ReleaseConfig(new ReleaseConfigConditionDto()
            {
                AppId = namespaceInfo.Data.AppId,
                Token = namespaceInfo.Data.Token,
                ClusterName = "default",
                Env = env,
                NamespaceName = namespaceInfo.Data.Namespace,
                ReleasedBy = releaseUserId,
                ReleaseTitle = "添加/修改" + key.ToString() + "的配置",
                ReleaseComment = "添加/修改" + key.ToString() + "的配置",
                Portal_address = portAdderess
            });

            if (releaseConfigResult == null || !releaseConfigResult.IsSuccess)
            {
                WriteLog("ReleaseConfig", systemInfo.Data.Name, systemInfo.Data.Id, "发布配置",releaseConfigResult.Msg);
                result.Msg = "发布配置失败，请联系管理员";
                return result;
            }
            result.IsSuccess = true;
            return result;
        }
        private ResponseModel<ReleaseConfigInfoDto> GetEffectiveConfigInfo(Bas_System systemInfo, Ass_Apollo namespaceInfo)
        {
            var releaseConfigDto = apolloConfigService.GetEffectiveConfigInfo(new SingleNamespaceConditionDto()
            {
                NamespaceName = namespaceInfo.Namespace,
                AppId = namespaceInfo.AppId,
                Token = namespaceInfo.Token,
                ClusterName = "default",
                Env = env,
                Portal_address = portAdderess
            });
            if(releaseConfigDto.IsSuccess==false)
            {
                WriteLog("GetEffectiveConfigInfo", systemInfo.Name, systemInfo.Id, "获取配置", releaseConfigDto.Msg);
            }
          
            return releaseConfigDto;
        }


        private void WriteLog(string method,string systemName,string systemId,string failureHead,string failureReason,string parameters="")
        {
            Task.Run(() =>
            {
                ExceptionlessClient.Default.CreateLog("Brc_PaaS.Bll.Apollo.Apollo."+method, $"业务系统：{systemName}(系统Id为【{systemId}】)，于【{DateTime.Now.ToString("s")}】{failureHead}失败。失败原因：【{failureReason}】"+(string.IsNullOrWhiteSpace(parameters)?"": ("参数为："+parameters)), LogLevel.Error).Submit();
            });
        }
    }
}
